#include <vcl.h>
#pragma hdrstop

#include <Outils.h>
#include "CRadBtn.h"
#include "CGBox.h""
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//
static inline void ValidCtrCheck(CRadioButton *)
    {
    new CRadioButton(NULL);
    }


namespace Cradbtn
    {
    void __fastcall PACKAGE Register()
        {
        TComponentClass classes[1] = {__classid(CRadioButton)};
        RegisterComponents("EIC Ctrlstd", classes, 0);
		}
	}

//////////////////////////////////////
//
// CRadioButton
//
// Fonction: Constructeur
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
__fastcall CRadioButton::CRadioButton(TComponent* Owner)
	: TCustomControl(Owner)
	{
    m_asRefWebHelp      = EmptyStr;
	FChecked            = false;
	inherited::TabStop  = true;
	bFocused            = false;
	ParentColor         = true;

	Width               = DEFAULT_WIDTH;
	Height              = DEFAULT_HEIGHT;

	BmpOption           = NULL;
	LCaption            = NULL;
   m_iGroupe           = 0;
   m_Reference         = EmptyStr;

	LoadBmpOption();
	InitCaption();
   }


__fastcall CRadioButton::~CRadioButton()
{
//  if( ComponentState.Contains( csDesigning )&& LCaption )
      delete LCaption;
  delete BmpOption;
}

//////////////////////////////////////
//
// SetAlignment
//
// Fonction: Initialise la position du Radio par / au Caption
//
// P.E.: Alignment
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::SetAlignment( enum TRadButAlign AAlignment )
    {
    FAlignment = AAlignment;
    Repaint();
    }



//////////////////////////////////////
//
// SetCaption
//
// Fonction: Initialise Caption
//
// P.E.: Caption
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::SetCaption( const AnsiString aCaption )
    {
    inherited::Caption = aCaption;
    InitCaption();
    Repaint();
    }



//////////////////////////////////////
//
// SetChecked
//
// Fonction: Initialise Checked
//
// P.E.: Checked
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::SetChecked( bool bChecked )
	{
	if( bChecked )
		UncheckedLast();
	FChecked = bChecked;

	Repaint();
	}



//////////////////////////////////////
//
// SetEnabled
//
// Fonction: Initialise Enabled
//
// P.E.: Enabled
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::SetEnabled(     bool        bEnabled )
    {
    inherited::Enabled  = bEnabled;
    LCaption->Enabled   = bEnabled;
    Repaint();
    }

//////////////////////////////////////
//
// SetReadOnly
//
// Fonction: Initialise ReadOnly
//
// P.E.: ReadOnly
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::SetReadOnly(    bool        bReadOnly )
    {
    FReadOnly           = bReadOnly;
    inherited::TabStop  = !bReadOnly;
    Repaint();
    }



//////////////////////////////////////
//
// GetCaption
//
// Fonction: Renvoie Caption
//
// P.E.: AUCUN
//
// P.S.: Caption
//
//////////////////////////////////////
AnsiString  __fastcall CRadioButton::GetCaption() /*const*/
    {
    return( inherited::Caption );
    }



//////////////////////////////////////
//
// GetEnabled
//
// Fonction: Renvoie Enabled
//
// P.E.: AUCUN
//
// P.S.: Enabled
//
//////////////////////////////////////
bool __fastcall CRadioButton::GetEnabled()
    {
    return( inherited::Enabled );
    }



//////////////////////////////////////
//
// Paint
//
// Fonction: Redessine le controle
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::Paint()
    {
    int TopOption       = ( Height - BmpOption->Height ) / 2;

    Canvas->CopyMode    = cmSrcCopy;

    LoadBmpOption();

    if( Alignment == eRdButLeftAlign )
        {
		Canvas->Draw( 1, TopOption, BmpOption );
        LCaption->Left  = BmpOption->Width + SIZE_ESP;
        }
    else
        {
        Canvas->Draw( Width - BmpOption->Width, TopOption, BmpOption );
        LCaption->Left  = 2;
        }

    LCaption->Top       = ( Height - LCaption->Height ) / 2;

    LCaption->Font->Assign( Font );
    LCaption->Caption   = Caption;
    if( LCaption->Height > Height - 4 )
        Height          = LCaption->Height + 4;
    if( LCaption->Width > Width )
        Width           = LCaption->Width + BmpOption->Width + SIZE_ESP + 20;

	DrawContour( bFocused );
    }



//////////////////////////////////////
//
// DrawContour
//
// Fonction: Dessine un cadre autour du Caption lorsque le
//           controle recoit la focalisation
//
// P.E.: Contour visible / non visible
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::DrawContour( bool bVisible )
	{
    int     i       = LCaption->Left  - 1;
    int     j       = LCaption->Top   - 1;
    TColor  CColor;

    if( bVisible )
        CColor = clBlack;
    else
        CColor = Color;

    while( i < LCaption->Left + LCaption->Width + 1 )
        {
        Canvas->Pixels[i][LCaption->Top-1]                  = CColor;
        Canvas->Pixels[i][LCaption->Top+LCaption->Height]   = CColor;
        i += 2;
        }

    while( j < LCaption->Top + LCaption->Height + 1 )
		{
        Canvas->Pixels[LCaption->Left-1][j]                 = CColor;
        Canvas->Pixels[LCaption->Left+LCaption->Width+1][j] = CColor;
        j += 2;
        }
    }



//////////////////////////////////////
//
// LoadBmpOption
//
// Fonction: Charge le Bmp correspondant a l'etat du check
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::LoadBmpOption()
    {
    AnsiString aEtat;
    enum StateCheck eState;

    if( BmpOption )
        {
        delete BmpOption;
        BmpOption = NULL;
        }

    try
        {
        BmpOption               = new Graphics::TBitmap();
        BmpOption->Height       = 13;
        BmpOption->Width        = 13;
		BmpOption->Canvas->Brush->Color = Color;
        BmpOption->Canvas->FillRect( BmpOption->Canvas->ClipRect );

        if( Enabled )
            {
            if(ReadOnly)
                {
                if( Checked )
                    eState = eDisabledChecked;
                else
                    eState = eDisabledUnChecked;
                }
            else
                {
                if( Checked )
                    eState = eChecked;
                else
                    eState = eUnChecked;
				}
            }
        else
            {
            if( Checked )
                eState = eDisabledChecked;
            else
                eState = eDisabledUnChecked;
            }

        BmpOption->Canvas->Brush->Color  = Color;
        BmpOption->Canvas->Pen->Color   = BmpOption->Canvas->Brush->Color;
        BmpOption->Canvas->Ellipse( 1, 1, 11, 11 );

        DrawCheck( eState );
        }

    catch(...)
        {
        }
    }



//////////////////////////////////////
//
// DrawCheck
//
// Fonction: Dessine l'Option du RadBut
//
// P.E.: Etat de l'Option
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::DrawCheck( enum StateCheck eState )
    {
    TColor ColFond;

    if( eState == eDisabledUnChecked || eState == eDisabledChecked )
        ColFond = Color;
    else
        ColFond = clWindow;//clBtnHighlight;

    BmpOption->Canvas->Brush->Color = ColFond;
    BmpOption->Canvas->Pen->Color   = ColFond;
    BmpOption->Canvas->Ellipse( 1, 1, 11, 11 );

    BmpOption->Canvas->Pen->Color   = clBlack;
    BmpOption->Canvas->MoveTo(  2,  8 );
    BmpOption->Canvas->LineTo(  1,  7 );
    BmpOption->Canvas->LineTo(  1,  4 );
    BmpOption->Canvas->LineTo(  4,  1 );
    BmpOption->Canvas->LineTo(  7,  1 );
    BmpOption->Canvas->LineTo(  8,  2 );
    BmpOption->Canvas->LineTo( 10,  2 );
    BmpOption->Canvas->Pixels[ 2 ][ 2 ] = clBlack;

    if( eState == eDisabledUnChecked || eState == eDisabledChecked )
        BmpOption->Canvas->Pen->Color = Color;
    else
        BmpOption->Canvas->Pen->Color   = cl3DLight;//clBtnFace;
    BmpOption->Canvas->MoveTo(  9,  3 );
	BmpOption->Canvas->LineTo( 10,  4 );
    BmpOption->Canvas->LineTo( 10,  7 );
    BmpOption->Canvas->LineTo(  7, 10 );
    BmpOption->Canvas->LineTo(  4, 10 );
    BmpOption->Canvas->LineTo(  3,  9 );
    BmpOption->Canvas->LineTo(  1,  9);
    BmpOption->Canvas->Pixels[ 9 ][ 9 ] = BmpOption->Canvas->Pen->Color;

    BmpOption->Canvas->Pen->Color   = clBtnShadow;
    BmpOption->Canvas->MoveTo(  1,  9 );
    BmpOption->Canvas->LineTo(  1,  8 );
    BmpOption->Canvas->LineTo(  0,  7 );
    BmpOption->Canvas->LineTo(  0,  4 );
    BmpOption->Canvas->LineTo(  1,  3 );
    BmpOption->Canvas->LineTo(  1,  2 );
    BmpOption->Canvas->LineTo(  2,  1 );
    BmpOption->Canvas->LineTo(  3,  1 );
    BmpOption->Canvas->LineTo(  4,  0 );
	BmpOption->Canvas->LineTo(  7,  0 );
    BmpOption->Canvas->LineTo(  8,  1 );
    BmpOption->Canvas->LineTo( 10,  1 );

    BmpOption->Canvas->Pen->Color   = clBtnHighlight;
    BmpOption->Canvas->MoveTo(  2, 10 );
    BmpOption->Canvas->LineTo(  3, 10 );
    BmpOption->Canvas->LineTo(  4, 11 );
    BmpOption->Canvas->LineTo(  7, 11 );
    BmpOption->Canvas->LineTo(  8, 10 );
    BmpOption->Canvas->LineTo(  9, 10 );
    BmpOption->Canvas->LineTo( 10,  9 );
    BmpOption->Canvas->LineTo( 10,  8 );
    BmpOption->Canvas->LineTo( 11,  7 );
    BmpOption->Canvas->LineTo( 11,  4 );
    BmpOption->Canvas->LineTo( 10,  3 );
    BmpOption->Canvas->LineTo( 10,  1 );

	if( eState == eChecked || eState == eDisabledChecked )
		{
		if( eState == eDisabledChecked )
			{
			BmpOption->Canvas->Brush->Color = clBtnShadow;
			BmpOption->Canvas->Pen->Color   = clBtnShadow;
			}
		else
			{
			BmpOption->Canvas->Brush->Color = clBlack;
			BmpOption->Canvas->Pen->Color   = clBlack;
			}

        BmpOption->Canvas->Ellipse( 4, 4, 8, 8 );
        }
    }


//////////////////////////////////////
//
// InitCaption
//
// Fonction: Cree le caption et l'initialise
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::InitCaption()
    {
    try
        {
        if( LCaption )
            {
            delete LCaption;
            LCaption = NULL;
            }

        LCaption                = new TLabel( this );
        LCaption->Visible       = true;
        LCaption->Parent        = this;
        LCaption->Font          = Font;
        LCaption->Font->Color   = clBlack;
        LCaption->Caption       = inherited::Caption;
		LCaption->AutoSize      = true;
        LCaption->Top           = ( Height - LCaption->Height ) / 2;
        LCaption->Transparent   = true;
        if( Alignment == eRdButLeftAlign )
            LCaption->Left      = BmpOption->Width + SIZE_ESP;
        else
            LCaption->Left      = 0;
        LCaption->OnClick       = CaptionClick;
        LCaption->FocusControl  = this;
        }

    catch(...)
        {
        }
    }


//////////////////////////////////////
//
// CaptionClick
//
// Fonction: Capture le click genere sur le caption et le retourne au controle
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::CaptionClick( TObject *Sender)
    {
    Click();
    }



//////////////////////////////////////
//
// Click
//
// Fonction: Capture Click
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::Click()
	{
	if( !FReadOnly )
		{
		Checked = true;

		if( OnCheck )
			OnCheck( this, Checked );

		inherited::Click();
		SetFocus();

		if(((TObject*)Parent)->ClassNameIs( "CGRadio" ))
			::SendMessage(((TWinControl*)Parent)->Handle, WM_LBUTTONUP, Tag, 0L );
		}
	}



//////////////////////////////////////
//
// KeyPress
//
// Fonction: Capture clavier
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::KeyPress( char &Key )
	{
	if( Key == VK_SPACE && !FReadOnly )
		{
		Checked = true;

		if(((TObject*)Parent)->ClassNameIs( "CGRadio" ))
			::SendMessage(((TWinControl*)Parent)->Handle, WM_LBUTTONUP, Tag, 0L );

		if( OnCheck )
			OnCheck( this, Checked );
		}
	}
//////////////////////////////////////
//
// KeyDown
//
// Fonction: Capture Touche F3
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::KeyDown(Word &Key, Classes::TShiftState Shift)
{
    if( Key == VK_F3 )
        VerifierRefWebHelp( m_asRefWebHelp );
}
//////////////////////////////////////
//
// UncheckedLast
//
// Fonction: Vérifie tous les CRadioButton contenus dans le Parent de celui-ci
//           et décoche celui du même groupe qui est coché.
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::UncheckedLast()
	{
   for (int i=0 ; i < Parent->ControlCount ; i++)
		{
		if(Parent->Controls[i]->ClassNameIs("CRadioButton")
         && Parent->Controls[i] != this
         && ((CRadioButton*)Parent->Controls[i])->Groupe == m_iGroupe
         && ((CRadioButton *)Parent->Controls[ i ])->Checked)
			{
         ((CRadioButton *)Parent->Controls[ i ])->Checked = false;
         if( ((CRadioButton *)Parent->Controls[ i ])->OnCheck )
            ((CRadioButton *)Parent->Controls[ i ])->OnCheck( this, false );
         return; //Comme il ne peut y en avoir qu'un de coché, inutile de poursuivre la recherche.
			}
		}
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// IsAnotherChecked ( appelee uniquement a la creation )                      //
//                                                                            //
// Test si un autre RadioBoutton est checked                                  //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
bool __fastcall CRadioButton::IsAnotherChecked()
	{
	int i ;

   for (i=0 ; i < Parent->ControlCount ; i++)
		{
		if(Parent->Controls[i]->ClassNameIs("CRadioButton")
		&& ((CRadioButton *)Parent->Controls[i])->Checked
      && Parent->Controls[i] != this
      && ((CRadioButton*)Parent->Controls[i])->Groupe == m_iGroupe)
 			return true;
		}
	return false;
	}



//////////////////////////////////////
//
// WndProc
//
// Fonction: Intercepte les evenements
//
// P.E.: Le message
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CRadioButton::WndProc( TMessage &Message )
	{
	switch( Message.Msg )
		{
		case WM_SETFOCUS:
			{
			if( !ComponentState.Contains( csDesigning ))
				{
				if( FReadOnly || !TabStop )
					{
					Message.Msg = WM_NULL;
					::SetFocus( GetNextDlgTabItem( Parent->Handle, Handle, false ));
					}
				else
					{
					bFocused    = true;
					Repaint();
					}
				}
			else
				{
				bFocused    = true;
				Repaint();
				}
			break;
			}


		case WM_KILLFOCUS:
			{
			bFocused = false;
			Repaint();
			break;
			}

		case BM_GETCHECK:
			{
			if( Checked )
                Message.Result = BST_CHECKED;
            else
                Message.Result = BST_UNCHECKED;
            return;
			}

		case WM_CREATE:
			{
			if( ComponentState.Contains( csDesigning ) && !IsAnotherChecked())
				Checked = true;
			break;
			}

		case WM_ENABLE:
			{
            Enabled = (bool)Message.WParam;
            break;
            }

		case WM_READONLY:
			{
            ReadOnly = (bool)Message.WParam;
            break;
			}

        case BM_SETCHECK:
            {
			Checked = (bool)Message.WParam;
            break;
            }
        }
    inherited::WndProc( Message );
	}



